package org.dizem.freepl0.compiler;

import org.dizem.freepl0.compiler.errormanager.ErrorManager;
import org.dizem.freepl0.compiler.reader.Reader;
import org.dizem.freepl0.compiler.symbol.Symbol;

/**
 * Created by IntelliJ IDEA.
 * User: DIZEM
 * Date: 11-2-2
 * Time: 下午2:52
 */
public class WordAnalysis {

	public static int IDENT_LENGTH = 11;
	public static int NUMBER_LENGTH = 9;
	public static int MAX_NUMBER = 2047;

	public int num;

	private char ch = ' ';
	private int line;
	private ErrorManager errorManager;
	private StringBuffer wordBuffer = new StringBuffer();


	public WordAnalysis(FPCompiler compiler) {
		this.reader = compiler.getReader();
		this.errorManager = compiler.getErrorManager();
	}

	private Reader reader;

	public Symbol getSymbol() {
		Symbol sym;

		while (ch == ' ' || ch == '\t' || ch == '\n' || ch == 13) {
			if (reader.isEnd()) {
				return Symbol.ENDFILE;
			}
			if (ch == '\n')
				line++;
			ch = reader.nextChar();
		}

		if (Character.isLetter(ch)) {
			wordBuffer.delete(0, wordBuffer.length());

			do {
				if (wordBuffer.length() < IDENT_LENGTH)
					wordBuffer.append(ch);
				ch = reader.nextChar();

			} while (Character.isLetter(ch) || Character.isDigit(ch));

			if (wordBuffer.length() > IDENT_LENGTH)
				errorManager.addError(26);

			return Symbol.find(getWord());

		} else if (Character.isDigit(ch)) {

			int len = 0;
			num = 0;
			sym = Symbol.NUMBER;

			do {
				num = num * 10 + ch - '0';
				len++;
				ch = reader.nextChar();

			} while ('0' <= ch && ch <= '9');

			if (len > NUMBER_LENGTH) {
				errorManager.addError(30);
				num = 0;
			}

			if (num > MAX_NUMBER) {
				errorManager.addError(31);
				num = 0;
			}

		} else if (ch == ':') {
			ch = reader.nextChar();

			if (ch == '=') {
				sym = Symbol.BECOMES;
				ch = reader.nextChar();

			} else
				sym = Symbol.NUL;

		} else if (ch == '<') {
			ch = reader.nextChar();

			if (ch == '=') {
				sym = Symbol.LEQ;
				ch = reader.nextChar();

			} else if (ch == '>') {
				sym = Symbol.NEQ;
				ch = reader.nextChar();

			} else
				sym = Symbol.LSS;

		} else if (ch == '>') {
			ch = reader.nextChar();

			if (ch == '=') {
				sym = Symbol.GEQ;
				ch = reader.nextChar();

			} else
				sym = Symbol.GTR;

		} else {
			switch (ch) {

				case '+':
					sym = Symbol.PLUS;
					break;

				case '-':
					sym = Symbol.MINUS;
					break;

				case '*':
					sym = Symbol.TIMES;
					break;

				case '/':
					sym = Symbol.SLASH;
					break;

				case '(':
					sym = Symbol.LPAREN;
					break;

				case ')':
					sym = Symbol.RPAREN;
					break;

				case '=':
					sym = Symbol.EQL;
					break;

				case '#':
					sym = Symbol.NEQ;
					break;

				case ',':
					sym = Symbol.COMMA;
					break;

				case '.':
					sym = Symbol.PERIOD;
					break;

				case ';':
					sym = Symbol.SEMICOLON;
					break;

				default:
					if (reader.isEnd()) {
						sym = Symbol.ENDFILE;
						break;

					} else {
						sym = Symbol.NUL;
						break;
					}
			}

			if (sym != Symbol.PERIOD)
				ch = reader.nextChar();
		}
		return sym;
	}


	public int getNum() {
		return num;
	}

	public int getLine() {
		return line;
	}

	public String getWord() {
		return wordBuffer.toString();
	}
}